package main

import (
	"fmt"
	"io"
	"net"
	"sync"
	"time"
)

const (
	OutTime = 3600
)

//定义Server结构体
type Server struct {
	Ip string
	Port int

	//在线用户
	OnlineMap map[string] *User
	mapLock sync.RWMutex
	//广播消息channel
	messageChannel chan string
}

//创建Server
func NewServer(ip string, port int) *Server {
	server := &Server{
		Ip: ip,
		Port: port,
		OnlineMap: make(map[string] *User),
		messageChannel: make(chan string),
	}
	return server
}

//启动Server
func (server *Server) Start()  {
	//1. listen
	listen, err := net.Listen("tcp", fmt.Sprintf("%s:%d", server.Ip, server.Port))
	if err != nil{
		fmt.Println("net.Listen error", err)
		return
	}
	//4. close listen socket
	defer listen.Close()
	
	go server.ListenMessage()

	for  {
		//2. accept
		accept, err := listen.Accept()
		if err != nil{
			fmt.Println("listen.Accept error", err)
			continue
		}
		//3. do handler
		go server.Handler(accept)
	}
}

//监听channel消息通道
func (server *Server) ListenMessage() {
	for  {
		msg :=  <- server.messageChannel
		server.mapLock.Lock()
		for _, user := range server.OnlineMap {
			user.Channel <- msg
		}
		server.mapLock.Unlock()
	}
}

//连接成功业务处理
func (server *Server) Handler(conn net.Conn) {
	//当前连接业务
	user := NewUser(conn, server)
	isLive := make(chan bool)
	//用户上线
	user.Online()
	//读取用户消息
	go server.ReadUserMessage(user, isLive)
	//阻塞当前handler
	for  {
		select {
		case <- isLive:
			//当前用户活跃，重置定时器

		case <- time.After(OutTime * time.Second):
			//已经超时
			//将当前user强制踢出
			user.SendMessage("您已被踢出")
			server.DeleteOnlineMap(user)
			//关闭连接，释放资源
			close(user.Channel)
			user.Conn.Close()
			return
		}
	}
}

//用户加入到在线用户表
func (server *Server) AddOnlineMap(user *User) {
	server.mapLock.Lock()
	server.OnlineMap[user.Name] = user
	server.mapLock.Unlock()
}

//用户从在线用户表删除
func (server *Server) DeleteOnlineMap(user *User) {
	server.mapLock.Lock()
	delete(server.OnlineMap, user.Name)
	server.mapLock.Unlock()
}

func (server *Server) GetUserByName(name string) (*User, bool) {
	user, ok := server.OnlineMap[name]
	return user, ok
}

//广播用户上线
func (server *Server) BroadcastOnline(user *User, msg string) {
	sendMsg := "[" + user.Address + "]" + user.Name + "：" + msg
	server.messageChannel <- sendMsg
}

//读取用户信息
func (server *Server) ReadUserMessage(user *User, isLive chan bool) {
	buf := make([]byte, 4096)
	//for循环，可以一直读取消息
	for {
		n, err := user.Conn.Read(buf)
		//用户下线
		if n == 0 {
			user.Offline()
			return
		}
		//读取失败
		if err != nil && err != io.EOF{
			fmt.Println("conn read error",  err)
			return
		}
		//取出末尾\n
		msg := string(buf[:n-1])
		//处理消息
		user.ReceiveMessage(msg)
		//标识用户正在活跃
		isLive <- true
	}
}

//遍历在线用户
func (server *Server) GetOnlineUsers(user *User)  {
	for _, online := range server.OnlineMap {
		msg := "[" + online.Address + "]" + online.Name + ":在线"
		user.SendMessage(msg)
	}
}
